import Taro from '@tarojs/taro'

/**
 * 跨平台兼容的存储工具
 */
export const storage = {
  /**
   * 获取存储数据
   * @param {string} key - 存储键
   * @returns {any} - 存储的值
   */
  getSync: (key) => {
    try {
      // 检查当前环境
      const env = Taro.getEnv()
      
      if (env === Taro.ENV_TYPE.WEB) {
        // H5 环境使用 localStorage
        const value = localStorage.getItem(key)
        return value ? JSON.parse(value) : null
      } else {
        // 小程序环境使用 Taro.getStorageSync
        return Taro.getStorageSync(key)
      }
    } catch (e) {
      console.error('获取存储失败:', e)
      return null
    }
  },

  /**
   * 设置存储数据
   * @param {string} key - 存储键
   * @param {any} data - 要存储的数据
   */
  setSync: (key, data) => {
    try {
      const env = Taro.getEnv()
      
      if (env === Taro.ENV_TYPE.WEB) {
        // H5 环境使用 localStorage
        localStorage.setItem(key, JSON.stringify(data))
      } else {
        // 小程序环境使用 Taro.setStorageSync
        Taro.setStorageSync(key, data)
      }
    } catch (e) {
      console.error('设置存储失败:', e)
    }
  },

  /**
   * 移除存储数据
   * @param {string} key - 存储键
   */
  removeSync: (key) => {
    try {
      const env = Taro.getEnv()
      
      if (env === Taro.ENV_TYPE.WEB) {
        // H5 环境使用 localStorage
        localStorage.removeItem(key)
      } else {
        // 小程序环境使用 Taro.removeStorageSync
        Taro.removeStorageSync(key)
      }
    } catch (e) {
      console.error('移除存储失败:', e)
    }
  },

  /**
   * 异步获取存储数据
   * @param {string} key - 存储键
   * @returns {Promise<any>} - 存储的值
   */
  get: async (key) => {
    try {
      const env = Taro.getEnv()
      
      if (env === Taro.ENV_TYPE.WEB) {
        // H5 环境使用 localStorage
        const value = localStorage.getItem(key)
        return value ? JSON.parse(value) : null
      } else {
        // 小程序环境使用 Taro.getStorage
        const result = await Taro.getStorage({ key })
        return result.data
      }
    } catch (e) {
      console.error('获取存储失败:', e)
      return null
    }
  },

  /**
   * 异步设置存储数据
   * @param {string} key - 存储键
   * @param {any} data - 要存储的数据
   */
  set: async (key, data) => {
    try {
      const env = Taro.getEnv()
      
      if (env === Taro.ENV_TYPE.WEB) {
        // H5 环境使用 localStorage
        localStorage.setItem(key, JSON.stringify(data))
      } else {
        // 小程序环境使用 Taro.setStorage
        await Taro.setStorage({ key, data })
      }
    } catch (e) {
      console.error('设置存储失败:', e)
    }
  }
}

/**
 * 跨平台兼容的网络请求工具
 */
export const request = {
  /**
   * 发起网络请求
   * @param {Object} options - 请求选项
   * @returns {Promise} - 请求结果
   */
  send: async (options) => {
    try {
      const env = Taro.getEnv()
      
      if (env === Taro.ENV_TYPE.WEB) {
        // H5 环境使用 fetch API
        const { url, method = 'GET', data, header = {} } = options
        
        const fetchOptions = {
          method,
          headers: {
            'Content-Type': 'application/json',
            ...header
          }
        }
        
        if (method !== 'GET' && data) {
          fetchOptions.body = JSON.stringify(data)
        }
        
        const response = await fetch(url, fetchOptions)
        const responseData = await response.json()
        
        return {
          statusCode: response.status,
          data: responseData,
          header: Object.fromEntries(response.headers.entries())
        }
      } else {
        // 小程序环境使用 Taro.request
        return await Taro.request(options)
      }
    } catch (error) {
      console.error('网络请求失败:', error)
      throw error
    }
  },

  /**
   * 上传文件
   * @param {Object} options - 上传选项
   * @returns {Promise} - 上传结果
   */
  uploadFile: async (options) => {
    try {
      const env = Taro.getEnv()
      
      if (env === Taro.ENV_TYPE.WEB) {
        // H5 环境使用 FormData 和 fetch
        const { url, filePath, name, header = {} } = options
        
        let fileToUpload = filePath
        
        // 如果filePath是blob URL，需要获取对应的File对象
        if (typeof filePath === 'string' && filePath.startsWith('blob:')) {
          // 从全局存储中获取原始File对象
          const fileMap = window.__fileMap__ || new Map()
          fileToUpload = fileMap.get(filePath)
          
          if (!fileToUpload) {
            // 如果没有找到原始File对象，尝试从blob URL获取
            const response = await fetch(filePath)
            const blob = await response.blob()
            fileToUpload = new File([blob], 'image.jpg', { type: blob.type })
          }
        }
        
        const formData = new FormData()
        formData.append(name, fileToUpload)
        
        const response = await fetch(url, {
          method: 'POST',
          headers: header,
          body: formData
        })
        
        const responseData = await response.text()
        
        return {
          statusCode: response.status,
          data: responseData
        }
      } else {
        // 小程序环境使用 Taro.uploadFile
        return await Taro.uploadFile(options)
      }
    } catch (error) {
      console.error('文件上传失败:', error)
      throw error
    }
  }
}

/**
 * 获取当前运行环境
 * @returns {string} - 环境类型
 */
export const getEnv = () => {
  try {
    return Taro.getEnv()
  } catch (e) {
    // 如果 Taro.getEnv 不可用，通过其他方式判断
    if (typeof window !== 'undefined' && window.document) {
      return 'WEB'
    }
    return 'UNKNOWN'
  }
}

/**
 * 检查是否为 H5 环境
 * @returns {boolean} - 是否为 H5 环境
 */
export const isH5 = () => {
  return getEnv() === Taro.ENV_TYPE.WEB || getEnv() === 'WEB'
}

/**
 * 检查是否为小程序环境
 * @returns {boolean} - 是否为小程序环境
 */
export const isMiniProgram = () => {
  const env = getEnv()
  return env === Taro.ENV_TYPE.WEAPP || 
         env === Taro.ENV_TYPE.ALIPAY || 
         env === Taro.ENV_TYPE.SWAN || 
         env === Taro.ENV_TYPE.TT || 
         env === Taro.ENV_TYPE.QQ
}

/**
 * 跨平台兼容的 UI 交互工具
 */
export const ui = {
  /**
   * 显示消息提示框
   * @param {Object} options - 提示选项
   */
  showToast: (options) => {
    if (isH5()) {
      // H5 环境下使用自定义 toast 实现
      const { title, icon = 'none', duration = 1500 } = options
      
      // 创建 toast 元素
      const toast = document.createElement('div')
      toast.style.cssText = `
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        background: rgba(0, 0, 0, 0.8);
        color: white;
        padding: 12px 20px;
        border-radius: 8px;
        font-size: 14px;
        z-index: 9999;
        max-width: 200px;
        text-align: center;
        word-wrap: break-word;
      `
      
      // 根据 icon 类型添加图标
      let iconHtml = ''
      if (icon === 'success') {
        iconHtml = '<div style="margin-bottom: 8px; font-size: 20px;">✓</div>'
      } else if (icon === 'error') {
        iconHtml = '<div style="margin-bottom: 8px; font-size: 20px;">✗</div>'
      } else if (icon === 'loading') {
        iconHtml = '<div style="margin-bottom: 8px; font-size: 16px;">⟳</div>'
      }
      
      toast.innerHTML = iconHtml + title
      document.body.appendChild(toast)
      
      // 自动移除
      setTimeout(() => {
        if (toast.parentNode) {
          document.body.removeChild(toast)
        }
      }, duration)
      
      return Promise.resolve()
    } else {
      return Taro.showToast(options)
    }
  },
  
  /**
   * 关闭所有页面，打开到应用内的某个页面
   * @param {Object} options - 跳转选项
   */
  redirectTo: (options) => {
    // Taro 在 H5 环境下已经处理了路由转换，直接使用原生 API
    return Taro.redirectTo(options)
  },
  
  /**
   * 保留当前页面，跳转到应用内的某个页面
   * @param {Object} options - 跳转选项
   */
  navigateTo: (options) => {
    // Taro 在 H5 环境下已经处理了路由转换，直接使用原生 API
    return Taro.navigateTo(options)
  },
   
   /**
    * 显示模态对话框
    * @param {Object} options - 对话框选项
    */
   showModal: (options) => {
     if (isH5()) {
       // H5 环境下使用原生 confirm/alert
       const { title, content, showCancel = true, confirmText = '确定', cancelText = '取消', success, fail } = options
       
       try {
         let result
         if (showCancel) {
           result = window.confirm(`${title}\n\n${content}`)
           success && success({ confirm: result, cancel: !result })
         } else {
           window.alert(`${title}\n\n${content}`)
           success && success({ confirm: true, cancel: false })
         }
         return Promise.resolve({ confirm: result || !showCancel, cancel: showCancel && !result })
       } catch (error) {
         fail && fail(error)
         return Promise.reject(error)
       }
     } else {
       return Taro.showModal(options)
     }
   },
   
   /**
    * 显示 loading 提示框
    * @param {Object} options - loading 选项
    */
   showLoading: (options) => {
     if (isH5()) {
       // H5 环境下使用自定义 loading 实现
       const { title = '加载中...', mask = true } = options
       
       // 移除已存在的 loading
       const existingLoading = document.getElementById('taro-loading')
       if (existingLoading) {
         document.body.removeChild(existingLoading)
       }
       
       // 创建 loading 容器
       const loadingContainer = document.createElement('div')
       loadingContainer.id = 'taro-loading'
       loadingContainer.style.cssText = `
         position: fixed;
         top: 0;
         left: 0;
         width: 100%;
         height: 100%;
         z-index: 10000;
         display: flex;
         align-items: center;
         justify-content: center;
         background: ${mask ? 'rgba(0, 0, 0, 0.3)' : 'transparent'};
       `
       
       // 创建 loading 内容
       const loadingContent = document.createElement('div')
       loadingContent.style.cssText = `
         background: rgba(0, 0, 0, 0.8);
         color: white;
         padding: 20px;
         border-radius: 8px;
         text-align: center;
         font-size: 14px;
       `
       
       loadingContent.innerHTML = `
         <div style="margin-bottom: 10px; font-size: 20px; animation: spin 1s linear infinite;">⟳</div>
         <div>${title}</div>
         <style>
           @keyframes spin {
             0% { transform: rotate(0deg); }
             100% { transform: rotate(360deg); }
           }
         </style>
       `
       
       loadingContainer.appendChild(loadingContent)
       document.body.appendChild(loadingContainer)
       
       return Promise.resolve()
     } else {
       return Taro.showLoading(options)
     }
   },
   
   /**
    * 隐藏 loading 提示框
    */
   hideLoading: () => {
     if (isH5()) {
       const loading = document.getElementById('taro-loading')
       if (loading) {
         document.body.removeChild(loading)
       }
       return Promise.resolve()
     } else {
       return Taro.hideLoading()
     }
   },

   /**
    * 跨平台选择图片
    * @param {Object} options - 选择图片的配置
    * @returns {Promise} - 返回选择的图片信息
    */
   chooseImage: (options = {}) => {
      const env = Taro.getEnv()
      
      if (env === Taro.ENV_TYPE.WEB) {
        // H5环境使用input file
        return new Promise((resolve, reject) => {
          const input = document.createElement('input')
          input.type = 'file'
          input.accept = 'image/*'
          input.multiple = options.count > 1
          
          input.onchange = (event) => {
            const files = event.target.files
            if (files && files.length > 0) {
              const tempFilePaths = []
              const tempFiles = []
              
              // 初始化全局文件映射
              if (!window.__fileMap__) {
                window.__fileMap__ = new Map()
              }
              
              // 处理选择的文件
              for (let i = 0; i < Math.min(files.length, options.count || 1); i++) {
                const file = files[i]
                const url = URL.createObjectURL(file)
                
                // 将File对象存储到全局Map中
                window.__fileMap__.set(url, file)
                
                tempFilePaths.push(url)
                tempFiles.push({
                  path: url,
                  size: file.size,
                  type: file.type,
                  originalFileObj: file
                })
              }
              
              resolve({
                tempFilePaths,
                tempFiles
              })
            } else {
              reject(new Error('未选择文件'))
            }
          }
          
          input.onerror = () => {
            reject(new Error('选择文件失败'))
          }
          
          // 触发文件选择
          input.click()
        })
      } else {
        // 小程序环境使用原生API
        return new Promise((resolve, reject) => {
          Taro.chooseImage({
            ...options,
            success: resolve,
            fail: reject
          })
        })
      }
    }
 }